﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace Useful.GUI
{
    public class DataGridViewCellStyleContainer : IEnumerable<string>
    {
        private class ValueContainer
        {
            public DataGridViewCellStyle Style { get; private set; }
            public int Counter { get; set; }

            public ValueContainer(DataGridViewCellStyle style)
            {
                this.Style = style;
                this.Counter = 0;
            }
        }

        private readonly Dictionary<string, ValueContainer> styles = new Dictionary<string, ValueContainer>();

        private static string MakeKey(DataGridViewCellStyle style, Color foreColor, Color backColor, Color selectionBackColor, Font font, FontStyle fontStyle)
        {
            string res = null;

            res = String.Format("style = [{0}] + ForeColor = {1}, BackColor = {2}, SelectionBackColor = {3}, Font = {4}, FontStyle = {5}", style, foreColor, backColor, selectionBackColor, font, fontStyle);

            return res;
        }

        private static string MakeKeyForFont(Font font, FontStyle fontStyle)
        {
            return String.Format("Font = {0}, FontStyle = {1}", font, fontStyle);
        }

        private DataGridViewCellStyle ProcessGetCellStyle(DataGridViewCellStyle style, string styleName, Action<DataGridViewCellStyle> action)
        {
            ValueContainer res = null;

            if (!styles.TryGetValue(styleName, out res))
            {
                res = new ValueContainer(new DataGridViewCellStyle(style));

                action(res.Style);

                styles.Add(styleName, res);
            }
            else
                res.Counter++;

            return res.Style;
        }

        /*public DataGridViewCellStyle this[DataGridViewCellStyle style, FontStyle fontStyle]
        {
            get
            {
                string styleName = MakeKey(style, style.ForeColor, style.BackColor, style.SelectionBackColor, style.Font, fontStyle);

                return ProcessGetCellStyle(style, styleName, cs => {
                    cs.Font = new Font(style.Font, style.Font.Style | fontStyle);
                });
            }
        }

        public DataGridViewCellStyle this[DataGridViewCellStyle style, Color foreColor]
        {
            get
            {
                string styleName = MakeKey(style, foreColor, style.BackColor, style.SelectionBackColor, style.Font, style.Font.Style);

                return ProcessGetCellStyle(style, styleName, cs =>
                {
                    cs.ForeColor = foreColor;
                });
            }
        }

        public DataGridViewCellStyle this[DataGridViewCellStyle style, Color foreColor, Color backColor]
        {
            get
            {
                string styleName = MakeKey(style, foreColor, backColor, style.SelectionBackColor, style.Font, style.Font.Style);

                return ProcessGetCellStyle(style, styleName, cs =>
                {
                    cs.ForeColor = foreColor;
                    cs.BackColor = backColor;
                });
            }
        }

        public DataGridViewCellStyle this[DataGridViewCellStyle style, Color foreColor, Color backColor, Color selectionBackColor]
        {
            get
            {
                string styleName = MakeKey(style, foreColor, backColor, selectionBackColor, style.Font, style.Font.Style);

                return ProcessGetCellStyle(style, styleName, cs =>
                {
                    cs.ForeColor = foreColor;
                    cs.BackColor = backColor;
                    cs.SelectionBackColor = selectionBackColor;
                });
            }
        }*/

        public Font GetFont(DataGridViewCellStyle style, FontStyle fontStyle)
        {
            string styleName = MakeKeyForFont(style.Font, fontStyle);

            DataGridViewCellStyle newStyle = ProcessGetCellStyle(style, styleName, cs =>
            {
                cs.Font = new Font(style.Font, style.Font.Style | fontStyle);
            });

            return newStyle.Font;
        }

        public IEnumerator<string> GetEnumerator()
        {
            return styles.Keys.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public int GetCounter(string styleName)
        {
            return styles[styleName].Counter;
        }

        public DataGridViewCellStyle GetStyle(string styleName)
        {
            return styles[styleName].Style;
        }
    }
}
